package alipay

import (
	"bytes"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

type Result struct {
	Response *http.Response
	Err      error
}

type FileParam struct {
	FiledName string
	Name      string
	FormFile  multipart.File
}

// FromDataPost Content-Type: multipart/form-data
func FromDataPost(url string, params map[string][]byte, files []FileParam, headers map[string]string) Result {
	buf := new(bytes.Buffer)
	w := multipart.NewWriter(buf)

	for k, v := range params {
		if fw, err := w.CreateFormField(k); err == nil {
			fw.Write(v)
		}
	}

	for _, file := range files {
		if createFormFile, err := w.CreateFormFile(file.FiledName, file.Name); err == nil {
			readAll, _ := io.ReadAll(file.FormFile)
			createFormFile.Write(readAll)
		}
	}
	w.Close()

	req, err := http.NewRequest(http.MethodPost, url, buf)
	if err != nil {
		return Result{nil, err}
	}
	req.Header.Set("Content-Type", w.FormDataContentType())
	for key, header := range headers {
		req.Header.Set(key, header)
	}
	client := &http.Client{
		Timeout: 60 * time.Second,
	}
	res, err := client.Do(req)
	if err != nil {
		return Result{nil, err}
	}
	return Result{res, nil}
}

func JsonPost(url string, params []byte, headers map[string]string) Result {
	log.Printf("请求参数：%s \n", string(params))

	reader := bytes.NewReader(params)
	req, err := http.NewRequest(http.MethodPost, url, reader)
	if err != nil {
		log.Printf("建立链接失败：%s \n", err)
		return Result{nil, err}
	}
	req.Header.Set("Content-Type", "application/json;charset=utf-8")
	for k, v := range headers {
		req.Header.Set(k, v)
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		log.Printf("发送请求失败：%s \n", err)
		return Result{nil, err}
	}
	return Result{res, nil}
}

// www-from-urlencoded
func FromUrlencodedPost(host string, params map[string]interface{}) Result {
	form := url.Values{}
	for k, v := range params {
		switch v.(type) {
		case string:
			form.Add(k, v.(string))
		case int:
			form.Add(k, strconv.Itoa(v.(int)))
		}
	}
	resp, err := http.PostForm(host, form)
	return Result{resp, err}
}

func (r Result) StatusCode() int {
	return r.Response.StatusCode
}

func (r Result) Body() ([]byte, error) {
	body, err := io.ReadAll(r.Response.Body)
	if err != nil {
		return nil, err
	}
	defer r.Response.Body.Close()
	return body, nil
}

func (r Result) Header() http.Header {
	return r.Response.Header
}
